package com.xuecheng.publish.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.content.model.dto.TeachplanDTO;
import com.xuecheng.content.common.enums.content.CourseModeEnum;
import com.xuecheng.content.common.exception.ExceptionCast;
import com.xuecheng.content.common.util.JsonUtil;
import com.xuecheng.publish.common.constant.CoursePubTemplateKey;
import com.xuecheng.publish.common.constant.CoursePublishErrorCode;
import com.xuecheng.publish.common.util.QiniuUtils;
import com.xuecheng.publish.entity.CourseMarket;
import com.xuecheng.publish.entity.CoursePub;
import com.xuecheng.publish.entity.CoursePubMsg;
import com.xuecheng.publish.mapper.CoursePubMapper;
import com.xuecheng.publish.service.CoursePubService;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 课程发布 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class CoursePubServiceImpl extends ServiceImpl<CoursePubMapper, CoursePub> implements CoursePubService {

    @Autowired
    private Configuration configuration;
    /*
    发布课程页面
     */
    @Value("${file.qiniu.accessKey}")
    private String accessKey;

    @Value("${file.qiniu.secretKey}")
    private String secretKey;

    @Value("${file.qiniu.bucket}")
    private String bucket;

    @Value("${course.publish.position}")
    private String position;
    //业务分析：
    //  1.实现消息的幂等性
    //      跟coursePubId  isPub
    //      查询CoursePub表
    //  2.生成课程页面
    //      数据模型-通过CoursePub
    //      页面模板-通过Configuration
    //          无需创建，Spring-boot-starter-Freemarker已经将Configuration对象创建出来
    //  3.将页面上传到cdn服务上
    //  4.修改课程发布状态is_pub

    @Override
    public void publishPage(CoursePubMsg coursePubMsg) {

        //  1.实现消息的幂等性
        //      跟coursePubId  isPub
        //      查询CoursePub表
        //判断课程发布有没有操作完--发布页面
        LambdaQueryWrapper<CoursePub> pubLambdaQueryWrapper = new LambdaQueryWrapper<>();
        pubLambdaQueryWrapper.eq(CoursePub::getId, coursePubMsg.getPubId());
        pubLambdaQueryWrapper.eq(CoursePub::getIsPub, CoursePub.IS_PUB);

        int count = this.count(pubLambdaQueryWrapper);

        // 如果消息已经发布并将页面上传到cdn中，无需抛出异常，只需要记录操作信息
        if (count>0){
            log.info("课程发布消息已经产生页面，无需操作，课程id："+coursePubMsg.getPubId());
            return;
        }
        //  2.生成课程页面
        //      数据模型-通过CoursePub
        //      页面模板-通过Configuration
        //          无需创建，Spring-boot-starter-Freemarker已经将Configuration对象创建出来
        Long pubId = coursePubMsg.getPubId();
        CoursePub coursePub = this.getById(pubId);
        if (ObjectUtils.isEmpty(coursePub)){
            ExceptionCast.cast(CoursePublishErrorCode.E_120209);
        }
        String html = null;
        try {
            Map<String, Object> dataMap = generateDataMap(coursePub);

            Template template = configuration.getTemplate("learing_article.ftl");

            html = FreeMarkerTemplateUtils.processTemplateIntoString(template, dataMap);
        } catch (Exception e) {
            log.error("课程生成详情页失败，coursePub：{}",coursePubMsg.getPubId());
            ExceptionCast.cast(CoursePublishErrorCode.E_120209);
        }
        //  3.将页面上传到cdn服务上

        // html名称：coursePubId.html
        // cdn上：pages/页面
        try {
            String fileKey = position+coursePubMsg.getPubId()+".html";

            QiniuUtils.upload2Qiniu(accessKey, secretKey, bucket, html, fileKey);
        } catch (Exception e) {
            log.error("课程详情页上传cdn失败，coursePub：{}",coursePubMsg.getPubId());
            ExceptionCast.cast(CoursePublishErrorCode.E_120210);
        }


        //  4.修改课程发布状态is_pub
        LambdaUpdateWrapper<CoursePub> pubUpdateWrapper = new LambdaUpdateWrapper<>();
        pubUpdateWrapper.set(CoursePub::getIsPub, CoursePub.IS_PUB);
        pubUpdateWrapper.set(CoursePub::getChangeDate, LocalDateTime.now());
        pubUpdateWrapper.eq(CoursePub::getId, coursePubMsg.getPubId());

        boolean result = this.update(pubUpdateWrapper);

        if (!result) {
            ExceptionCast.cast(CoursePublishErrorCode.E_120212);
        }


    }


    private Map<String, Object> generateDataMap(CoursePub coursepub) {

        // 1.声明数据模型DataMap
        HashMap<String, Object> dataMap = new HashMap<>();

        // 课程发布数据
        dataMap.put(CoursePubTemplateKey.COURSEPUB, coursepub);


        String marketJsonString = coursepub.getMarket();
        CourseMarket courseMarket = JsonUtil.jsonToObject(marketJsonString, CourseMarket.class);

        // 课程营销数据
        dataMap.put(CoursePubTemplateKey.COURSEMARKET, courseMarket);


        // 课程模式枚举数据
        CourseModeEnum[] values = CourseModeEnum.values();
        dataMap.put(CoursePubTemplateKey.COURSETEACHMODEENUMS, values);


        // 课程计划数据
        String teachplanJsonString = coursepub.getTeachplan();

        TeachplanDTO teachplanDTO = JsonUtil.jsonToObject(teachplanJsonString, TeachplanDTO.class);
        dataMap.put(CoursePubTemplateKey.TEACHPLANNODE, teachplanDTO);

        return dataMap;
    }

}
